package javasec.seed;

import java.rmi.AlreadyBoundException;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

import java.util.HashMap;
import java.util.Map;
import java.util.Vector;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

import java.net.URLClassLoader;
import java.net.URL;

import java.lang.reflect.Method;

import javax.rmi.ssl.SslRMIClientSocketFactory;
import javax.rmi.ssl.SslRMIServerSocketFactory;


public abstract class Seed extends UnicastRemoteObject implements SeedInterface
{
	public Map<String,Seed> seeds=new HashMap<String,Seed>();
	public String seedName=this.getClass().getSimpleName();
	public String packageName=seedName.toLowerCase();

	public Seed() throws RemoteException
	{
		super(0,SeedServer.csf,SeedServer.ssf);
		
		if(SeedServer.rmiRegistry!=null)
		try
		{
			System.out.println("binding "+seedName);
			SeedServer.rmiRegistry.bind(seedName,this);
		}
		catch(AlreadyBoundException e)
		{
			e.printStackTrace();
		}
	}

	public String getName() throws RemoteException
	{
		return seedName;
	}

	public SeedMethod[] getMethods() throws RemoteException
	{
		Vector<SeedMethod> methodVector=new Vector<SeedMethod>();

		// for each method in this class
		for(Method method:this.getClass().getMethods())
		{
			// determine if this is an exposed method
			if(method.isAnnotationPresent(Exposed.class))
			{
				methodVector.add(new SeedMethod(method));
			}
		}

		return (SeedMethod[])methodVector.toArray(new SeedMethod[0]);
	}

	public Object invokeMethod(String methodName, Object[] arguments) throws RemoteException
	{
		//ManagerSeed.instance.notifyClients("methodinvoke",methodName+" was invoked");
		ManagerSeed.notifyClients(new SeedNotification("methodinvoke",methodName+" was invoked"));
		
		Class[] parameterTypes=null;
		if(arguments!=null)parameterTypes=new Class[arguments.length];
		Method method=null;
		Object result=null;

		System.out.println(this.getName()+": invoking "+methodName);

		if(arguments!=null)
		{
			for(int x=0;x<arguments.length;++x)
			{
				parameterTypes[x]=arguments[x].getClass();
			}
		}

		try
		{
			method=this.getClass().getMethod(methodName,parameterTypes);
			result=method.invoke(this,arguments);
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}

		return result;
	}
}
